import {
	ControlVOBase,
	deepCopy,
	LayoutUtil,
	verifyDynamicLogic,
} from '@/core';
import {
	IParam,
	IPanelControllerParams,
	ICtrlActionResult,
	IEvent,
	IHttpResponse,
	IPanelModel,
} from '@/core/interface';
import { IPanelAbility } from '@/core/interface/widgets/ability';
import { IPanelController } from '@/core/interface/widgets/controller';
import { PanelActionType } from '@/core/interface/widgets/event';
import { IPanelStore } from '@/core/interface/widgets/store';
import PanelService from '@/core/modules/ctrl-service/panel-service';
import { DECtrlController } from './de-ctrl-controller';

/**
 * 面板控制器
 *
 * @export
 * @class PanelController
 * @extends {(DECtrlController<A | PanelEventActionType, IPanelStore>)}
 * @implements {IPanelController<T>}
 * @template A
 */
export class PanelController
	extends DECtrlController<PanelActionType, IPanelStore, IPanelAbility>
	implements IPanelController<IPanelStore, IPanelAbility>
{
	/**
	 * 面板模型
	 *
	 * @protected
	 * @type {IPanelModel}
	 * @memberof PanelController
	 */
	protected declare readonly model: IPanelModel;

	/**
	 * 部件服务
	 *
	 * @type {PanelService<ControlVOBase>}
	 * @memberof PanelController
	 */
	declare ctrlService: PanelService<ControlVOBase>;

	/**
	 * Creates an instance of PanelController.
	 * @param {IPanelControllerParams} params
	 * @memberof PanelController
	 */
	public constructor(
		params: IPanelControllerParams<PanelActionType, IPanelAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param { IPanelControllerParams<PanelActionType, IPanelAbility>} params
	 * @memberof PanelController
	 */
	protected processCtrlInit(
		params: IPanelControllerParams<PanelActionType, IPanelAbility>
	) {
		super.processCtrlInit(params);
		this.isLoadDefault = params.isLoadDefault === true;
		this.viewType = params.viewType;
		this.data = params.data;
		Object.assign(this.store, {
			layoutData: {},
			data: {},
			layoutModelDetails: {},
		});

		setTimeout(() => {
			console.log(this.store.layoutModelDetails);
		}, 3000);
	}

	/**
	 * 初始化后（对store做处理）
	 *
	 * @protected
	 * @param {ICtrlControllerParams<T, A>} params
	 * @memberof PanelController
	 */
	protected afterCtrlInit(
		params: IPanelControllerParams<PanelActionType, IPanelAbility>
	) {
		super.afterCtrlInit(params);
		this.computedUIData();
	}

	/**
	 * 默认加载
	 *
	 * @type {boolean}
	 * @memberof PanelController
	 */
	public isLoadDefault: boolean = false;

	/**
	 * 视图类型
	 *
	 * @private
	 * @type {string}
	 * @memberof PanelController
	 */
	private viewType?: string;

	/**
	 * 传入面板数据
	 *
	 * @private
	 * @type {IParam}
	 * @memberof PanelController
	 */
	private data?: IParam;

	/**
	 * 初始化面板
	 *
	 * @protected
	 * @return {*}
	 * @memberof PanelController
	 */
	protected async initLayout() {
		const { rootLayoutDetailNames, layoutItems } = this.model;
		if (rootLayoutDetailNames && layoutItems) {
			this.beforeAsyncAction('initLayout', {}, {});
			for (let i = 0; i < rootLayoutDetailNames.length; i++) {
				const name = rootLayoutDetailNames[i];
				const rootItem = layoutItems[name];
				if (!rootItem) {
					return;
				}
				await this.initLayoutItem(rootItem);
			}
			this.afterAsyncAction('initLayout', { success: true });
		}
	}

	/**
	 * 初始化面板项
	 *
	 * @private
	 * @param {*} layoutModelItem
	 * @param {number} [index]
	 * @memberof PanelController
	 */
	private async initLayoutItem(layoutModelItem: any, index?: number) {
		const { name } = layoutModelItem;
		const { layoutItems } = this.model;
		const { context, viewParams } = this.store;
		const layoutModelDetail = LayoutUtil.getLayoutItemInstance({
			...layoutModelItem,
			viewType: this.viewType,
			panel: this,
		});
		if (!(index || index === 0)) {
			await layoutModelDetail.load(context, viewParams);
			this.store.layoutModelDetails[name] = layoutModelDetail;
			this.store.layoutData[name] = layoutModelDetail.getData();
		} else {
			layoutModelDetail.setIndex(index);
			await layoutModelDetail.load(context, viewParams);
			this.store.layoutModelDetails[`${name}_${index}`] = layoutModelDetail;
			this.store.layoutData[`${name}_${index}`] = layoutModelDetail.getData();
		}
		if (layoutModelDetail && layoutModelDetail.details) {
			if (layoutModelDetail.dataRegionType === 'MULTIDATA') {
				const multiData = layoutModelDetail.getData();
				if (multiData && multiData.length > 0) {
					for (let i = 0; i < multiData.length; i++) {
						for (let j = 0; j < layoutModelDetail.details.length; j++) {
							const key = layoutModelDetail.details[j];
							if (layoutItems && layoutItems[key]) {
								await this.initLayoutItem(layoutItems[key], i);
							}
						}
					}
				}
			} else {
				for (let i = 0; i < layoutModelDetail.details.length; i++) {
					const key = layoutModelDetail.details[i];
					if (layoutItems && layoutItems[key]) {
						await this.initLayoutItem(layoutItems[key], index);
					}
				}
			}
		}
	}

	/**
	 * 计算UI展示数据
	 *
	 * @param {IParam} args
	 * @memberof PanelController
	 */
	public async computedUIData(args?: IParam) {
		const { dataMode } = this.model;
		if (dataMode === 3) {
			// this.viewCtx.appGlobal[this.controlInstance.M.dataName] = this.data;
		} else if (dataMode === 4) {
			// this.viewCtx.routeViewGlobal[this.controlInstance.M.dataName] = this.data;
		} else if (dataMode === 5) {
			// this.viewCtx.viewGlobal[this.controlInstance.M.dataName] = this.data;
		} else {
			if (this.isLoadDefault) {
				await this.computeLoadState(args);
			}
		}
		await this.initLayout();
	}

	/**
	 * 计算数据加载模式
	 *
	 * @param {IParam} [args]
	 * @memberof PanelController
	 */
	public async computeLoadState(args?: IParam) {
		const { dataMode } = this.model;
		if (dataMode === 0) {
			//  0：不获取，使用传入数据
			if (this.data) {
				this.store.data = this.data;
			}
		} else if (dataMode === 1) {
			//  1：存在传入数据时，不获取
			if (this.data) {
				this.store.data = this.data;
			} else {
				await this.load();
			}
		} else if (dataMode === 2) {
			//  2：始终获取
			await this.load();
		}
	}

	/**
	 * 数据加载
	 *
	 * @param {IParam} [opts={}]
	 * @param {boolean} [pageReset=false]
	 * @return {*}  {Promise<IHttpResponse>}
	 * @memberof PanelController
	 */
	public async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const { context, viewParams } = this.store;
		const { fetchAction } = this.actions;
		if (!fetchAction) {
			console.warn('未配置加载行为');
			return { ok: false, data: this.getData(), rowData: { status: 500 } };
		}
		const arg: any = {};
		const queryParams: IParam = {};
		const parentData: IParam = {};
		this.emit('beforeLoad', [parentData]);
		//	视图查询参数
		if (parentData && Object.keys(parentData).length > 0) {
			Object.assign(queryParams, parentData);
		}
		//	额外查询参数
		if (opts && Object.keys(opts).length > 0) {
			Object.assign(queryParams, opts);
		}
		const tempViewParams = Object.assign(deepCopy(viewParams), queryParams);
		Object.assign(arg, { viewParams: tempViewParams });
		const tempContext = deepCopy(context);
		this.beforeAsyncAction('load', tempContext, arg);
		try {
			const response: IHttpResponse = await this.ctrlService.search(
				fetchAction,
				tempContext,
				arg
			);
			if (!response || !response.success) {
				this.afterAsyncAction('load', response);
				return {
					ok: false,
					data: this.getData(),
					rowData: response,
				};
			}
			this.handleLoadDataChange(response.data);
			this.emit('load', response.data);
			this.afterAsyncAction('load', response);
			return {
				ok: true,
				data: this.getData(),
				rowData: response,
			};
		} catch (error: any) {
			this.afterAsyncAction('load', error);
			return {
				ok: false,
				data: this.getData(),
				rowData: error,
			};
		}
	}

	/**
	 * 处理加载数据变更
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof PanelController
	 */
	protected handleLoadDataChange(data: IParam[]): void {
		this.store.data = data;
	}

	/**
	 * 处理组件行为
	 *
	 * @param {IEvent<string>} actionParam
	 * @memberof PanelController
	 */
	public handleComponentAction(
		actionParam: IEvent<string>,
		index?: number
	): void {
		const { name, action, data } = actionParam;
		switch (action) {
			case 'panelButtonAction':
				this.handlePanelButtonAction(name, data, index);
				break;
			case 'valueChange':
				this.handlePanelValueChange(name, data, index);
				break;
			default:
				break;
		}
	}

	/**
	 * 处理面板按钮行为
	 *
	 * @private
	 * @param {string} name
	 * @param {MouseEvent} event
	 * @param {number} [index]
	 * @memberof PanelController
	 */
	private handlePanelButtonAction(
		name: string,
		event: MouseEvent,
		index?: number
	) {
		const { context, viewParams } = this.store;
		const fullName = index || index === 0 ? `${name}_${index}` : name;
		const layoutModel = this.store.layoutModelDetails[fullName];
		if (layoutModel) {
			let tempData: IParam[] = [];
			const data: IParam = layoutModel.getData();
			const ability: any = layoutModel.getAbility();
			const logic = layoutModel.uiAction;
			if (data) {
				if (data instanceof Array) {
					tempData = [...data];
				} else {
					tempData = [data];
				}
			}
			App.getViewLogicHelper().executeViewLogic(
				context,
				viewParams,
				tempData,
				event,
				ability,
				logic
			);
		}
	}

	/**
	 * 处理面板值变化
	 *
	 * @private
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @return {*}
	 * @memberof PanelController
	 */
	private handlePanelValueChange(name: string, value: any, index?: number) {
		const fullName = index || index === 0 ? `${name}_${index}` : name;
		if (!fullName || !this.store.layoutData.hasOwnProperty(fullName)) {
			return;
		}
		this.store.layoutData[fullName] = value;
		this.store.layoutModelDetails[fullName].setData(value);
		this.panelLogic(name, index);
		this.computeButtonAuthState();
	}

	/**
	 * 计算按钮权限状态
	 *
	 * @private
	 * @memberof PanelController
	 */
	private async computeButtonAuthState() {
		for (const key in this.store.layoutModelDetails) {
			const layoutModel = this.store.layoutModelDetails[key];
			if (layoutModel.itemType == 'BUTTON') {
				await layoutModel.computeActionAuthState();
			}
		}
	}

	/**
	 * 面板逻辑
	 *
	 * @private
	 * @param {string} name
	 * @param {number} [index]
	 * @memberof PanelController
	 */
	private panelLogic(name: string, index?: number): void {
		const { layoutData } = this.store;
		const { layoutItems } = this.model;
		if (layoutItems) {
			Object.values(layoutItems).forEach((item: IParam) => {
				item.groupLogics?.forEach((logic: IParam) => {
					let relatedNames = logic.relatedDetailNames || [];
					if (Object.is(name, '') || relatedNames.indexOf(name) != -1) {
						let tempLogic = deepCopy(logic);
						if (index || index === 0) {
							tempLogic.dEFDName = `${tempLogic.dEFDName}_${index}`;
						}
						const fullName =
							index || index === 0 ? `${item.name}_${index}` : item.name;
						let ret = verifyDynamicLogic(layoutData, tempLogic);
						switch (tempLogic.logicCat) {
							// 动态空输入，不满足则必填
							case 'ITEMBLANK':
								this.store.layoutModelDetails[fullName].required = !ret;
								break;
							// 动态启用，满足则启用
							case 'ITEMENABLE':
								this.store.layoutModelDetails[fullName].disabled = !ret;
								break;
							// 动态显示，满足则显示
							case 'PANELVISIBLE':
								this.store.layoutModelDetails[fullName].visible = ret;
								break;
						}
					}
				});
			});
		}
	}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof PanelController
	 */
	public getAbility(): IPanelAbility {
		return {
			...super.getAbility(),
			load: this.load.bind(this),
		};
	}
}
